<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
            "http://www.w3.org/TR/REC-html40/loose.dtd">
<HTML>
<HEAD>



<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<META name="GENERATOR" content="hevea 1.08">
<LINK rel="stylesheet" type="text/css" href="umsroot.css">
<TITLE>
Examples of Using Attributed Variables
</TITLE>
</HEAD>
<BODY >
<A HREF="umsroot101.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="umsroot093.html"><IMG SRC ="contents_motif.gif" ALT="Up"></A>
<A HREF="umsroot103.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
<HR>

<H2 CLASS="section"><A NAME="htoc227">16.9</A>&nbsp;&nbsp;Examples of Using Attributed Variables</H2><UL>
<LI><A HREF="umsroot102.html#toc127">Variables with Enumerated Domains</A>
</UL>

<A NAME="toc127"></A>
<H3 CLASS="subsection"><A NAME="htoc228">16.9.1</A>&nbsp;&nbsp;Variables with Enumerated Domains</H3>
As an example, let us implement variables of enumerable types
using attributes.
We choose to represent these variable as attributed variables
whose attribute is
a enum/1 structure with a list holding the values the variable may take,
e.g.
<BLOCKQUOTE CLASS="quote"><PRE CLASS="verbatim">
X{enum([a,b,c])}
</PRE></BLOCKQUOTE>
We have to specify now what should happen when such a variable is
bound. This is done by writing a handler for the <B>unify</B> operation.
The predicate unify_enum/2 defined below is this
handler.
Its first argument is the value that the attributed variable has been bound to,
the second is the attribute that the bound attributed variable had
(keep in mind that the system has already bound the attributed variable to the
new value). We distinguish two cases:<BR>
<BR>
First, the attributed variable has been
bound to another attributed variable (1st clause of unify_enum/2).
In this case, we form the intersection between the two lists
of admissible values. If it is empty, we fail.
If it contains exactly one value, we can instantiate the remaining
attributed variable with this value.
Otherwise, we bind it to a new attributed variable whose attribute represents
the remaining admissible values.<BR>
<BR>
Second, when the attributed variable has been bound to a non-variable, the
task that remains for the handler is merely to check if this binding
was admissible (2nd clause of unify_enum/2).
<BLOCKQUOTE CLASS="quote"><PRE CLASS="verbatim">
[eclipse 2]: module(enum).
warning: creating a new module in module(enum)
[enum 3]: [user].
:- meta_attribute(enum, [unify:unify_enum/2, print:print_enum/2]).
:- import setarg/3 from sepia_kernel.

% unify_enum(+Term, Attribute)
unify_enum(_, Attr) :-
    /*** ANY + VAR ***/
    var(Attr).                  % Ignore if no attribute for this extension
unify_enum(Term, Attr) :-
    compound(Attr),
    unify_term_enum(Term, Attr).

unify_term_enum(Value, enum(ListY)) :-
    nonvar(Value),               % The attributed variable was instantiated
    /*** NONVAR + META ***/
    memberchk(Value, ListY).
unify_term_enum(Y{AttrY}, AttrX) :-
    -?-&gt;
    unify_enum_enum(Y, AttrX, AttrY).

unify_enum_enum(_, AttrX, AttrY) :-
    var(AttrY),                         % no attribute for this extension
    /*** VAR + META ***/
    AttrX = AttrY.                      % share the attribute
unify_enum_enum(Y, enum(ListX), AttrY) :-
    nonvar(AttrY),
    /*** META + META ***/
    AttrY = enum(ListY),
     intersection(ListX, ListY, ListXY),
     ( ListXY = [Val] -&gt;
            Y = Val
     ;   
            ListXY \= [],
            setarg(1, AttrY, ListXY)
     ).  

print_enum(enum(List), Attr) :-
    -?-&gt;
    Attr = List.
 user       compiled traceable 1188 bytes in 0.03 seconds

yes.
[enum 4]: A{enum([yellow, blue, white, green])}
                = B{enum([orange, blue, red, yellow])}.

A = B = A{[blue, yellow]}
yes.
[enum 5]: A{enum([yellow, blue, white, green])}
                = B{enum([orange, blue, red, black])}.

A = B = blue
yes.
[enum 6]: A{enum([yellow, blue, white, green])} = white.

A = white
yes.
[enum 7]: A{enum([yellow, blue, white, green])} = red.

no (more) solution.

</PRE></BLOCKQUOTE>
Some further remarks on this code:
<A NAME="@default945"></A>
<A NAME="@default946"></A>
<A NAME="@default947"></A>
The second clause of <B>unify_term_enum/2</B>
is a <B>matching clause</B>, as indicated
by the <B>&minus;?&minus;&gt;</B> guard.
A matching clause is the only way to decompose an attributed variable.
Note that this clause matches only calls that have an attributed variable
with nonempty <B>enum</B> attribute on the
first argument position.<BR>
<BR>
<HR>
<A HREF="umsroot101.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="umsroot093.html"><IMG SRC ="contents_motif.gif" ALT="Up"></A>
<A HREF="umsroot103.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
</BODY>
</HTML>
